/*
 * Copyright (c) 2025 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
import React, { forwardRef, useCallback, useEffect, useImperativeHandle, useMemo, useRef, useState } from 'react';
import { I18nManager, Dimensions } from 'react-native';
import { useBreakpointValue, BreakpointMap } from '@hadss/react_native_breakpoints';
import type { WithSpringConfig, WithTimingConfig } from 'react-native-reanimated';
import type { AdaptiveSheetProps } from './types';
import type { AdaptiveSheetMethods } from '../../types';
import { SHEET_TYPE } from '../../constants';
import AdaptiveBottomSheet from '../adaptiveBottomSheet';
import type { AdaptiveBottomSheetProps } from '../adaptiveBottomSheet/types';
import AdaptiveSideSheet from '../adaptiveSideSheet';
import { SIDE_POSITION } from '../adaptiveSideSheet/types';
import type { AdaptiveSideSheetProps } from '../adaptiveSideSheet/types';
import AdaptiveCenterSheet from '../adaptiveCenterSheet';
import type { AdaptiveCenterSheetProps } from '../adaptiveCenterSheet/types';
import AdaptiveSheetBackdrop from '../adaptiveSheetBackdrop';
import type { AdaptiveSheetBackdropProps } from '../adaptiveSheetBackdrop/types';
import AdaptiveSideSheetBackdrop from '../adaptiveSideSheet/AdaptiveSideSheetBackdrop';
import { DEFAULT_SHEET_TYPE, DEFAULT_INDEX, DEFAULT_ANIMATE_ON_MOUNT } from './constants';

// 组件定义
type AdaptiveSheet = AdaptiveSheetMethods;

const AdaptiveSheetComponent = forwardRef<AdaptiveSheet, AdaptiveSheetProps>(function AdaptiveSheet(
  {
    // configuration
    prefertype = DEFAULT_SHEET_TYPE,
    breakpointConfig,
    index = DEFAULT_INDEX,
    snapPoints,
    bottomSnapPoints,
    sideSnapPoints,
    animateOnMount = DEFAULT_ANIMATE_ON_MOUNT,

    // specific props
    bottomSheetProps,
    sideSheetProps,
    centerSheetProps,

    // common props
    title,
    backdropComponent,

    // callbacks
    onStateChange,
    onSheetTypeChange,

    // children
    children,
  },
  ref,
) {
  const [currentIndex, setCurrentIndex] = useState(index);
  const [containerWidth, setContainerWidth] = useState(Dimensions.get('window').width);

  // 记录类型切换前的 index，用于切换后恢复
  const indexBeforeTypeChange = useRef<number>(-1);

  // 记录上次类型切换的时间，用于限制切换频率
  const lastTypeChangeTime = useRef<number>(0);

  // 默认底部弹窗背景遮罩
  const defaultBottomBackdrop: React.FC<Record<string, unknown>> = useCallback(
    (props: Record<string, unknown>) => (
      <AdaptiveSheetBackdrop
        {...(props as Record<string, unknown>)}
        appearsOnIndex={0}
        disappearsOnIndex={-1}
        pressBehavior="close"
        style={[props.style as Record<string, unknown>, { backgroundColor: 'rgba(0, 0, 0, 0.64)' }]}
      />
    ),
    [],
  );

  // 默认侧边弹窗背景遮罩
  const defaultSideBackdrop: React.FC<Record<string, unknown>> = useCallback(
    (props: Record<string, unknown>) => (
      <AdaptiveSideSheetBackdrop
        {...(props as Record<string, unknown>)}
        style={[props.style as Record<string, unknown>, { backgroundColor: 'rgba(0, 0, 0, 0.64)' }]}
      />
    ),
    [],
  );

  // 使用单一 ref，指向当前激活的弹窗
  const sheetRef = useRef<AdaptiveSheetMethods | null>(null);
  const previousSheetType = useRef<SHEET_TYPE | null>(null);
  const previousPosition = useRef<SIDE_POSITION | null>(null); // 跟踪 position 变化
  const isTransitioning = useRef<boolean>(false); // 标记是否正在切换类型
  const transitionTimer = useRef<NodeJS.Timeout | null>(null); // 切换防抖定时器
  const debounceTimer = useRef<NodeJS.Timeout | null>(null); // 类型变化防抖定时器
  const stableSheetType = useRef<SHEET_TYPE | null>(null); // 稳定的弹窗类型
  const mountCounter = useRef<number>(0); // 挂载计数器，确保每次类型切换都重新挂载
  const lastOnChangeIndex = useRef<number | null>(null); // 跟踪上一次 onChange 的 index
  const onChangeTimer = useRef<NodeJS.Timeout | null>(null); // onChange 防抖定时器

  // 构建断点映射配置
  const breakpointMap: BreakpointMap<SHEET_TYPE> = useMemo(() => {
    if (breakpointConfig) {
      // 使用自定义配置
      return breakpointConfig;
    }

    // 默认配置：0-599 底部，600-833 居中，834+ 右侧
    // 配合自定义断点值：setBreakpoints({ xs: 320, sm: 600, md: 834, lg: 1440, xl: Infinity })
    return {
      base: SHEET_TYPE.BOTTOM, // 默认值（小于最小断点）
      xs: SHEET_TYPE.BOTTOM, // 0-320px: 底部
      sm: SHEET_TYPE.BOTTOM, // 320-600px: 底部（实际 0-599）
      md: SHEET_TYPE.CENTER, // 600-834px: 居中（实际 600-833）
      lg: SHEET_TYPE.SIDE, // 834-1440px: 右侧（实际 834+）
      xl: SHEET_TYPE.SIDE, // 1440px+: 右侧
    };
  }, [breakpointConfig]);

  // 使用 useBreakpointValue 自动根据断点返回弹窗类型
  const autoSheetType = useBreakpointValue(breakpointMap);

  // 如果用户指定了类型，使用用户指定的；否则使用自动计算的
  const currentSheetType = useMemo(() => {
    const newType = prefertype === SHEET_TYPE.AUTO ? autoSheetType || SHEET_TYPE.BOTTOM : prefertype;

    // 如果正在切换中，忽略新的类型变化（防止快速连续切换）
    if (isTransitioning.current) {
      return stableSheetType.current || newType;
    }

    // 触发类型变化回调（移除 onSheetTypeChange 依赖，使用 ref）
    if (previousSheetType.current !== null && previousSheetType.current !== newType) {
      // 限制类型切换频率，避免频繁切换导致闪退
      const now = Date.now();
      const timeSinceLastChange = now - lastTypeChangeTime.current;
      const MIN_TYPE_CHANGE_INTERVAL = 300; // 最小切换间隔 300ms

      if (timeSinceLastChange < MIN_TYPE_CHANGE_INTERVAL) {
        return newType; // 忽略过于频繁的切换
      }

      lastTypeChangeTime.current = now; // 更新切换时间

      // 记录当前 index，用于类型切换后恢复
      if (currentIndex !== -1) {
        indexBeforeTypeChange.current = currentIndex;

        // 先关闭当前弹窗，避免多个弹窗同时显示
        setCurrentIndex(-1);
      }

      // 增加挂载计数器，强制重新挂载组件
      mountCounter.current += 1;

      // 清除之前的防抖定时器
      if (debounceTimer.current) {
        clearTimeout(debounceTimer.current);
        debounceTimer.current = null;
      }

      // 延迟触发回调，避免快速连续变化
      debounceTimer.current = setTimeout(() => {
        onSheetTypeChange?.(newType, previousSheetType.current!);
        debounceTimer.current = null;
      }, 50); // 50ms 防抖
    }

    previousSheetType.current = newType;
    stableSheetType.current = newType;

    return newType;
  }, [prefertype, autoSheetType, currentIndex]); // 添加 currentIndex 依赖

  // 简化：直接返回单一 ref
  const getActiveRef = useCallback(() => {
    return sheetRef.current;
  }, []);

  const snapToIndex = useCallback(
    (nextIndex: number, animationConfigs?: WithSpringConfig | WithTimingConfig): void => {
      const activeRef = getActiveRef();
      activeRef?.snapToIndex(nextIndex, animationConfigs);
      setCurrentIndex(nextIndex);
    },
    [currentSheetType, getActiveRef],
  );

  const snapToPosition = useCallback(
    (position: number | string, animationConfigs?: WithSpringConfig | WithTimingConfig): void => {
      const activeRef = getActiveRef();
      activeRef?.snapToPosition(position, animationConfigs);
    },
    [getActiveRef],
  );

  const expand = useCallback(
    (animationConfigs?: WithSpringConfig | WithTimingConfig): void => {
      const activeRef = getActiveRef();
      activeRef?.expand(animationConfigs);
    },
    [getActiveRef],
  );

  const collapse = useCallback(
    (animationConfigs?: WithSpringConfig | WithTimingConfig): void => {
      const activeRef = getActiveRef();
      activeRef?.collapse(animationConfigs);
    },
    [getActiveRef],
  );

  const close = useCallback(
    (animationConfigs?: WithSpringConfig | WithTimingConfig): void => {
      const activeRef = getActiveRef();
      activeRef?.close(animationConfigs);
      setCurrentIndex(-1);
    },
    [getActiveRef],
  );

  const forceClose = useCallback(
    (animationConfigs?: WithSpringConfig | WithTimingConfig): void => {
      const activeRef = getActiveRef();
      activeRef?.forceClose(animationConfigs);
      setCurrentIndex(-1);
    },
    [getActiveRef],
  );

  useImperativeHandle(ref, () => ({
    snapToIndex,
    snapToPosition,
    expand,
    collapse,
    close,
    forceClose,
  }));

  const handleStateChange = useCallback(
    (newIndex: number) => {

      // 防止重复调用相同的 index
      if (lastOnChangeIndex.current === newIndex && onChangeTimer.current) {
        return;
      }

      lastOnChangeIndex.current = newIndex;

      // 清除之前的定时器
      if (onChangeTimer.current) {
        clearTimeout(onChangeTimer.current);
      }

      // 设置新的定时器，200ms 后重置（从 50ms 增加到 200ms）
      // 避免动画过程中频繁触发 onChange
      onChangeTimer.current = setTimeout(() => {
        lastOnChangeIndex.current = null;
        onChangeTimer.current = null;
      }, 200);

      setCurrentIndex(newIndex);
      onStateChange?.(newIndex);
    },
    [onStateChange],
  );


  // 同步外部 index prop 到内部状态
  // 使用 ref 跟踪上一次的 index，避免无限循环
  const previousIndexRef = useRef(index);

  useEffect(() => {
    // 只有当外部 index 真正改变时才同步（不是内部状态改变）
    if (index !== previousIndexRef.current) {
      previousIndexRef.current = index;

      // 如果正在类型切换中，跳过同步（由类型切换 useEffect 处理）
      if (isTransitioning.current) {
        return;
      }

      if (index === currentIndex) {
        return;
      }

      // 更新内部状态
      setCurrentIndex(index);

      // 同步到底层弹窗
      const activeRef = getActiveRef();
      if (activeRef) {
        try {
          if (index !== -1) {
            activeRef.snapToIndex(index);
          } else {
            activeRef.close();
          }
        } catch (error) {
          console.warn('[AdaptiveSheet] Failed to sync index to sheet:', error);
        }
      }
    }
  }, [index, getActiveRef, currentIndex]); // 添加 currentIndex 依赖用于比较

  // 监听屏幕宽度变化
  useEffect(() => {
    let previousWidth = containerWidth;
    let updateTimer: NodeJS.Timeout | null = null;

    const subscription = Dimensions.addEventListener('change', ({ window }) => {
      const newWidth = window.width;

      // 只有当宽度真正变化时才更新
      if (newWidth !== previousWidth) {
        previousWidth = newWidth;

        // 清除之前的定时器
        if (updateTimer) {
          clearTimeout(updateTimer);
        }

        // 延迟更新，避免快速连续变化
        // 增加防抖时间，避免频繁切换导致闪退
        updateTimer = setTimeout(() => {
          setContainerWidth(newWidth);
          updateTimer = null;
        }, 300); // 300ms 防抖（从 100ms 增加到 300ms）
      }
    });

    return (): void => {
      subscription?.remove();
      if (updateTimer) {
        clearTimeout(updateTimer);
      }
    };
  }, []); // 移除 containerWidth 依赖，避免循环

  // 初始化动画：组件挂载时如果 index 不为 -1，则打开弹窗
  useEffect(() => {
    let rafId: number | null = null;

    if (animateOnMount && index !== -1) {
      rafId = requestAnimationFrame(() => {
        const activeRef = getActiveRef();
        if (activeRef) {
          try {
            activeRef.snapToIndex(index);
          } catch (error) {
            console.error('[AdaptiveSheet] Error during initial animation:', error);
          }
        }
      });
    }

    // 清理函数：取消未执行的 requestAnimationFrame
    return (): void => {
      if (rafId !== null) {
        cancelAnimationFrame(rafId);
      }
    };
  }, []); // 只在挂载时执行一次

  // 当弹窗类型切换时，处理状态同步
  useEffect(() => {
    let rafId: number | null = null;
    let isMounted = true;

    // 如果正在切换中，清除之前的定时器
    if (transitionTimer.current) {
      clearTimeout(transitionTimer.current);
      transitionTimer.current = null;
    }

    // 标记开始切换
    isTransitioning.current = true;

    // 检查是否需要恢复之前的 index
    const shouldRestoreIndex = indexBeforeTypeChange.current !== -1;
    const targetIndex = shouldRestoreIndex ? indexBeforeTypeChange.current : currentIndex;

    // 如果需要打开弹窗（当前打开或需要恢复）
    if (targetIndex !== -1) {
      // 延迟一帧，确保新组件已挂载
      rafId = requestAnimationFrame(() => {
        // 检查组件是否仍挂载
        if (!isMounted) {
          isTransitioning.current = false;
          indexBeforeTypeChange.current = -1;
          return;
        }

        const activeRef = getActiveRef();
        if (activeRef) {
          try {
            activeRef.snapToIndex(targetIndex);

            // 如果是恢复 index，更新 currentIndex 和 previousIndexRef
            if (shouldRestoreIndex) {
              setCurrentIndex(targetIndex);
              previousIndexRef.current = targetIndex; // 同步更新，避免外部 index 同步冲突
              indexBeforeTypeChange.current = -1; // 清除保存的 index
            }
          } catch (error) {
            console.error('[AdaptiveSheet] Error calling snapToIndex:', error);
          }
        }

        // 延迟标记切换完成，避免快速连续切换
        // 增加防抖时间，避免频繁切换导致闪退
        transitionTimer.current = setTimeout(() => {
          isTransitioning.current = false;
          transitionTimer.current = null;
        }, 300); // 300ms 防抖（从 100ms 增加到 300ms）
      });
    } else {
      // 如果是关闭状态，立即标记切换完成
      isTransitioning.current = false;
    }

    // 清理函数：取消未执行的 requestAnimationFrame 并标记为已卸载
    return (): void => {
      isMounted = false;
      if (rafId !== null) {
        cancelAnimationFrame(rafId);
      }
      if (transitionTimer.current) {
        clearTimeout(transitionTimer.current);
        transitionTimer.current = null;
      }
      isTransitioning.current = false;
    };
  }, [currentSheetType, currentIndex, getActiveRef]); // 依赖项包含所有使用的变量

  // 组件卸载时的全局清理
  useEffect(() => {
    return (): void => {
      // 清理所有定时器
      if (debounceTimer.current) {
        clearTimeout(debounceTimer.current);
        debounceTimer.current = null;
      }
      if (transitionTimer.current) {
        clearTimeout(transitionTimer.current);
        transitionTimer.current = null;
      }
      if (onChangeTimer.current) {
        clearTimeout(onChangeTimer.current);
        onChangeTimer.current = null;
      }

      // 重置所有状态
      isTransitioning.current = false;
      stableSheetType.current = null;
      lastOnChangeIndex.current = null;
    };
  }, []); // 只在挂载和卸载时执行

  // 真正的单一 return：根据类型选择要渲染的组件
  // 使用联合类型来明确 SheetComponent 和 sheetProps 的可能类型
  // 虽然在渲染时需要类型断言,但在 switch 语句中已经确保了类型安全
  type SheetComponentType = typeof AdaptiveBottomSheet | typeof AdaptiveSideSheet | typeof AdaptiveCenterSheet;
  type SheetPropsType = AdaptiveBottomSheetProps | AdaptiveSideSheetProps | AdaptiveCenterSheetProps;

  let SheetComponent: SheetComponentType;
  let sheetProps: SheetPropsType;
  let sheetKey: string;

  switch (currentSheetType) {
    case SHEET_TYPE.BOTTOM: {
      SheetComponent = AdaptiveBottomSheet;
      sheetKey = 'bottom-sheet';
      sheetProps = {
        index: currentIndex,
        // 优先使用 bottomSnapPoints，如果没有则使用 snapPoints
        snapPoints: bottomSnapPoints || bottomSheetProps?.snapPoints || snapPoints,
        animateOnMount,
        // 如果用户没有提供 backdropComponent，使用默认的
        backdropComponent: backdropComponent || defaultBottomBackdrop,
        onStateChange: handleStateChange,
        ...bottomSheetProps,
        children,
      } as AdaptiveBottomSheetProps;
      break;
    }

    case SHEET_TYPE.SIDE: {
      SheetComponent = AdaptiveSideSheet;
      sheetKey = 'side-sheet';

      // 自动检测 RTL（阿拉伯语等从右到左的语言）
      // RTL 语言时从左侧弹出，LTR 语言时从右侧弹出
      const isRTL = I18nManager.isRTL;
      const defaultPosition = isRTL ? SIDE_POSITION.LEFT : SIDE_POSITION.RIGHT;
      const finalPosition = sideSheetProps?.position || defaultPosition;

      // 检测 position 变化，如果变化则增加 mountCounter
      if (previousPosition.current !== null && previousPosition.current !== finalPosition) {
        mountCounter.current += 1;
      }
      previousPosition.current = finalPosition;

      sheetProps = {
        index: currentIndex,
        // 优先使用 sideSnapPoints，如果没有则使用 snapPoints
        snapPoints: sideSnapPoints || sideSheetProps?.snapPoints || snapPoints,
        // 优先使用用户指定的 position，否则根据 RTL 自动选择
        position: finalPosition,
        animateOnMount,
        // 如果用户没有提供 backdropComponent，使用默认的
        backdropComponent: backdropComponent || defaultSideBackdrop,
        onStateChange: handleStateChange,
        // 传递当前屏幕宽度，确保百分比计算正确
        containerWidth: containerWidth,
        ...sideSheetProps,
        children,
      } as AdaptiveSideSheetProps;

      break;
    }

    case SHEET_TYPE.CENTER: {
      SheetComponent = AdaptiveCenterSheet;
      sheetKey = 'center-sheet';
      sheetProps = {
        index: currentIndex,
        title,
        animateOnMount,
        onStateChange: handleStateChange,
        ...centerSheetProps,
        children,
      } as AdaptiveCenterSheetProps;
      break;
    }

    default:
      console.warn('[AdaptiveSheet] Unknown sheet type:', currentSheetType);
      return null;
  }

  const componentKey = `${sheetKey}-${mountCounter.current}`;

  return <SheetComponent key={componentKey} ref={sheetRef} {...(sheetProps as unknown as Record<string, unknown>)} />;
});

const AdaptiveSheet = React.memo(AdaptiveSheetComponent, (prevProps, nextProps) => {
  // 如果 index 变化，需要重渲染
  if (prevProps.index !== nextProps.index) {
    return false;
  }

  // 如果 prefertype 变化，需要重渲染
  if (prevProps.prefertype !== nextProps.prefertype) {
    return false;
  }

  // 如果 snapPoints 变化，需要重渲染
  if (prevProps.snapPoints !== nextProps.snapPoints) {
    return false;
  }

  if (prevProps.children !== nextProps.children) {
    // 如果 children 是 React 元素，比较 key
    if (React.isValidElement(prevProps.children) && React.isValidElement(nextProps.children)) {
      const prevKey = prevProps.children.key;
      const nextKey = nextProps.children.key;
      if (prevKey !== nextKey) {
        return false; // key 变化，需要重渲染
      }
    }
    // 如果 children 不是 React 元素，或者 key 相同，则认为 children 没有变化
  }

  return true;
});
AdaptiveSheet.displayName = 'AdaptiveSheet';

export default AdaptiveSheet;
